package se.statifyme.server.store;

import java.util.Collection;
import java.util.Date;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.Query;

import se.statifyme.server.entities.OwnedItem;
import se.statifyme.shared.IllegalOperationException;
import se.statifyme.shared.StringUtils;

public class OwnedItemStoreImpl<E extends OwnedItem> extends AbstractStore<E> implements OwnedItemStore<E> {
	
	public OwnedItemStoreImpl(Class<E> entityClass) {
		super(entityClass);
	}

	@Override
	public E get(String id, String ownerId) throws IllegalOperationException {
		E result;
		assertOwnerId(ownerId);
		EntityManager manager = getManager();
		try {
			result = manager.find(entityClass, id);
			if (result != null) {
				assertOwner(result, ownerId);
			} else {
				throw new IllegalOperationException("Item with ID \"" + id + "\" does not exist.");
			}
		} finally {
			manager.close();
		}

		return result;
	}

	@Override
	public Collection<E> getAll(String ownerId) {
		assertOwnerId(ownerId);
		EntityManager manager = getManager();
		try {
			Query query = manager.createQuery(String.format("SELECT e FROM %s e WHERE e.ownerId = :ownerId", TYPE));
			query.setParameter("ownerId", ownerId);
			
			@SuppressWarnings("unchecked")
			List<E> result = query.getResultList();
			
			result.size();
			
			return result;
		} finally {
			manager.close();
		}
	}

	@Override
	public void save(E item, String ownerId) throws IllegalOperationException {
		assertOwnerId(ownerId);
		EntityManager manager = getManager();
		final String itemId = item.getId();
		Date date = new Date();
		if (StringUtils.isBlank(itemId)) {
			item.setId(null);
			item.setCreated(date);
			item.setOwnerId(ownerId);
		} else {
			E existingItem = get(itemId);
			if (existingItem == null) {
				throw new IllegalOperationException("Item with ID \"" + itemId + "\" does not exist.");
			}
			assertOwner(existingItem, ownerId);
		}
		item.setModified(date);
		try {
			manager.persist(item);
		} finally {
			manager.close();
		}
	}

	@Override
	public void delete(String id, String ownerId) throws IllegalOperationException {
		assertOwnerId(ownerId);
		EntityManager manager = getManager();
		try {
			E item = manager.find(entityClass, id);
			if (item != null) {
				assertOwner(item, ownerId);
				manager.remove(item);
			}
		} finally {
			manager.close();
		}
	}
	
	protected void assertOwner(E item, String ownerId) {
		if (item == null) {
			throw new IllegalArgumentException("Item must not be null");
		}
		assertOwnerId(ownerId);
		if (StringUtils.isNotBlank(item.getId())) {
			final String itemOwnerId = item.getOwnerId();
			if (StringUtils.isBlank(itemOwnerId)) {
				throw new IllegalArgumentException("Item must have an owner since its ID is set");
			} else if (!ownerId.equals(itemOwnerId)) {
				throw new IllegalArgumentException("Not owner of item");
			}
		} else {
			item.setOwnerId(ownerId);
		}
	}
	
	protected void assertOwnerId(String ownerId) {
		if (StringUtils.isBlank(ownerId)) {
			throw new IllegalArgumentException("Owner ID must not be blank");
		}
	}

}
